package com.supreme.nettyapp.generalclient.socketclient.handler2;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;

import java.util.Arrays;
import java.util.concurrent.TimeUnit;

public class SocketClientHandler extends SimpleChannelInboundHandler<ByteBuf> {

    private static byte[] simpleCommand(WaterGunEnum command, int arg) {
        short shortVal = (short) arg;
        byte[] instruction = new byte[6];
        instruction[0] = (byte) 0xff;
        instruction[1] = 0x01;
        instruction[2] = command.getValue();
        instruction[3] = (byte) (shortVal & 0xff);
        instruction[4] = (byte) (shortVal >> 8 & 0xff);
        instruction[5] = (byte) ((instruction[1] + instruction[2] + instruction[3] + instruction[4] + 1) & 0xff);
        return instruction;
    }

    private static byte[] bothCommand(WaterGunEnum command, int arg1, int arg2) {
        short shortVal1 = (short) arg1;
        short shortVal2 = (short) arg2;
        byte[] instruction = new byte[6];
        instruction[0] = (byte) 0xff;
        instruction[1] = command.getValue();
        instruction[2] = (byte) (shortVal1 & 0xff);
        instruction[3] = (byte) (shortVal1 >> 8 & 0xff);
        instruction[4] = (byte) (shortVal2 & 0xff);
        instruction[5] = (byte) (shortVal2 >> 8 & 0xff);
        return instruction;
    }

    /**
     * 检查心跳包
     *
     * @param bufferData
     * @return
     */
    private static boolean verifyHeartbeat(int[] bufferData) {
        return bufferData[5] == bufferData[1] + bufferData[2] + bufferData[3] + bufferData[4] + 1;
    }

    private int heartbeatCounter = 0;

    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        System.out.println("Client channelActive = " + ctx.name());
        ctx.channel().eventLoop().schedule(() -> {
            byte[] bytes = simpleCommand(WaterGunEnum.READ_STATUS, 0);
            ByteBuf readStatusBuf = Unpooled.copiedBuffer(bytes);
            ctx.writeAndFlush(readStatusBuf);
        }, 1000, TimeUnit.MILLISECONDS);
    }

    @Override
    protected void channelRead0(ChannelHandlerContext ctx, ByteBuf byteBuf) throws Exception {
        int[] data = new int[byteBuf.readableBytes()];
        for (int i = 0; i < byteBuf.readableBytes(); i++) {
            int unsignedInt = byteBuf.getByte(i) & 0xFF;
            data[i] = unsignedInt;
        }
        Arrays.stream(data).forEach(item -> {
            System.out.println("item: " + item + " hex: " + Integer.toHexString(item) + " bin: " + Integer.toBinaryString(item));
        });

        if (!verifyHeartbeat(data)) {
            if (++heartbeatCounter > 5) {
                System.out.println("通讯故障，客户端退出。");
                ctx.close();
                return;
            }
        } else {
            heartbeatCounter = 0;

            if (data[2] == 0xba) {
                boolean isFireAlarm = (data[3] & 0x01) == 1;
                System.out.println("isFireAlarm = " + isFireAlarm);

                boolean isStartup = (data[3] >> 1 & 0x01) == 1;
                System.out.println("isStartup = " + isStartup);

                boolean isOpenFeedback = (data[3] >> 2 & 0x01) == 1;
                System.out.println("isOpenFeedback = " + isOpenFeedback);

                boolean isCloseFeedback = (data[3] >> 3 & 0x01) == 1;
                System.out.println("isCloseFeedback = " + isCloseFeedback);

                int semiAutomatic = (data[3] >> 4 & 0x03);
                System.out.println("semiAutomatic = " + semiAutomatic);

                boolean isOpenInstruct = (data[3] >> 7 & 0x01) == 1;
                System.out.println("isOpenInstruct = " + isOpenInstruct);

                boolean isColumnar = (data[4] & 0x01) == 1;
                System.out.println("isColumnar = " + isColumnar);

                int deviceStatus = (data[4] >> 1) & 0x07;
                System.out.println("deviceStatus = " + deviceStatus);
                switch (deviceStatus) {
                    case 1:
//                        model.statestr = "复位中..";
                        break;
                    case 2:
//                        model.statestr = "复位失败";
                        break;
                    case 3:
//                        model.statestr = "监控中..";
                        break;
                    case 4:
//                        model.statestr = "扫描中..";
                        break;
                    case 5:
//                        model.statestr = "定位中..";
                        break;
                    case 6:
//                        model.statestr = "喷射中..";
                        break;
                    case 7:
//                        model.statestr = "定位完成";
                        break;
                }
            } else {
                if (data[2] < 100) {
                    if (data[2] % 2 == 1) {
//                        sp_param[bytes[2] / 2] = BitConverter.ToInt16(bytes, 3);
                    }
//                    model.CoordinateX = (Convert.ToSingle(sp_param[6]) / 10).ToString("0.0");
//                    model.CoordinateY = (Convert.ToSingle(sp_param[7]) / 10).ToString("0.0");
                }
            }
        }

        ctx.channel().eventLoop().schedule(() -> {
            byte[] bytes = simpleCommand(WaterGunEnum.READ_STATUS, 0);
            ByteBuf readStatusBuf = Unpooled.copiedBuffer(bytes);
            ctx.writeAndFlush(readStatusBuf);
        }, 1000, TimeUnit.MILLISECONDS);
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        System.out.println("cause.getMessage() = " + cause.getMessage());
        ctx.close();
    }
}
